package cn.kilo.domain.model.order.entity;

import cn.kilo.domain.support.TimeUtil;
import cn.kilo.types.common.Constants;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;

/**
 * @author kilok
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class OrderStaffEntity {
    private String staffId;

    private Long orderId;

    private String staffRole;

    private String staffName;
    //计时
    private Long time;

    private Integer distance;

    private String end;

    private String dateTime;

    public static StaffSalaryEntity getSalary(StaffEntity staffEntity, List<OrderStaffEntity> list, String role){
        if("sorter1".equals(role)){
            return sorter1Salary(staffEntity,list);
        }else if("sorter2".equals(role)){
            return sorter2Salary(staffEntity,list);
        }else if("guard".equals(role)){
            return guardSalary(staffEntity,list);
        }else{
            return null;
        }
    }



    private static StaffSalaryEntity sorter1Salary(StaffEntity staff, List<OrderStaffEntity> orderStaffList){
        double salary=0;
        Map<Integer,List<OrderStaffEntity>> map=new HashMap<>();
        if(null==orderStaffList) {
            return  StaffSalaryEntity.builder()
                    .userId(staff.getStaffId())
                    .dateTime(TimeUtil.getDayTime())
                    .salary(0)
                    .build();
        }
        for(OrderStaffEntity orderStaff:orderStaffList){
            List<OrderStaffEntity> list=map.getOrDefault(orderStaff.getDistance(),new ArrayList<>());
            list.add(orderStaff);
            map.put(orderStaff.getDistance(),list);
        }
        int inTime=0;
        double allTime=0L;
        Set<Integer> keys = map.keySet();
        for(Integer distance:keys){
            List<OrderStaffEntity> staffList=map.get(distance);
            double distanceTime=0L;
            for(OrderStaffEntity orderStaff:staffList){
                distanceTime+=orderStaff.getTime();
                if((orderStaff.getTime()/60<5)) {
                    inTime++;
                }
            }
            distanceTime+=staffList.size()/distanceTime;
            if(distanceTime>=2&&distanceTime<3){
                distanceTime= (double) (1500L) /(distance+450);
            }else if(distanceTime>=3){
                distanceTime= (double) (2500L) /(distance+450);
            }else{
                distanceTime= (double) (1500L) /(2*distance+900);
            }
            allTime+=distanceTime;
        }
        allTime/=keys.size();
        if(allTime>=1&&allTime<2){
            salary+=30*allTime;
        }else if(allTime>=2&&allTime<3){
            salary+=80;
        }else if(allTime>=3){
            salary+=100;
        }else{
            salary+=60*allTime;
        }

        long rate= (long) (inTime/orderStaffList.size());
        salary+=107*Math.exp(0.95*rate)-172;
        salary=(int)(0.8*(salary)/2*orderStaffList.size());
        if(staff.getWeather().equals(Constants.Weather.RAIN)){
            salary+=1000;
        }
        return StaffSalaryEntity.builder()
                .userId(staff.getStaffId())
                .dateTime(TimeUtil.getDayTime())
                .salary((int)salary)
                .role(staff.getRole())
                .number(orderStaffList.size())
                .rate(rate)
                .speed(allTime)
                .build();
    }

    private static StaffSalaryEntity sorter2Salary(StaffEntity staff,List<OrderStaffEntity> orderStaffList){
        if(null==orderStaffList) {
            return  StaffSalaryEntity.builder()
                    .userId(staff.getStaffId())
                    .dateTime(TimeUtil.getDayTime())
                    .salary(0)
                    .build();
        }
        Map<String,List<OrderStaffEntity>> map=new HashMap<>();
        double allTime=0L;
        int inTime=0;

        for(OrderStaffEntity orderStaff:orderStaffList){
            String[] split=orderStaff.getEnd().split(Constants.UNDERLINE);
            List<OrderStaffEntity> list=map.getOrDefault(split[0],new ArrayList<>());
            list.add(orderStaff);
            map.put(split[0],list);
        }
        Set<String> keys = map.keySet();

        for(String key:keys){
            List<OrderStaffEntity> list=map.get(key);
            double time=0L;
            for(OrderStaffEntity orderStaff:list){
                if(orderStaff.getTime()/60<12){
                    inTime++;
                }
                time+=orderStaff.getTime();
            }
            time/=list.size();
            if(time>=1.5&&time<2){
                time=((double) 99 /(4*Integer.parseInt(key)+10));
            }else if(time>=2){
                time=((double) 132 /(4*Integer.parseInt(key)+10));
            }else{
                time=((double) (33/(2*Integer.parseInt(key)+5))*time);
            }
            allTime+=time;
        }
        allTime/=keys.size();
        double salary=0;
        if(allTime>=1&&allTime<1.5){
            salary+=30*allTime;
        }else if(allTime>=1.5&&allTime<2){
            salary+=80;
        }else if(allTime>=2){
            salary+=100;
        }else{
            salary+=60*allTime;
        }
        double rate = (double)inTime/orderStaffList.size();
        salary+=17.14*Math.exp(2.44*rate)-74.11;
        salary/=2;
        salary=1.5*salary*orderStaffList.size();
        return StaffSalaryEntity.builder()
                .userId(staff.getStaffId())
                .salary((int)salary)
                .dateTime(TimeUtil.getDayTime())
                .role(staff.getRole())
                .number(orderStaffList.size())
                .rate(rate)
                .speed(allTime)
                .build();
    }


    private static StaffSalaryEntity guardSalary(StaffEntity staff,List<OrderStaffEntity> orderStaffList){
        if(null==orderStaffList) {
            return  StaffSalaryEntity.builder()
                    .userId(staff.getStaffId())
                    .dateTime(TimeUtil.getDayTime())
                    .salary(0)
                    .build();
        }
        Integer salary=orderStaffList.size()*25;
        return StaffSalaryEntity.builder()
                .userId(staff.getStaffId())
                .role(staff.getRole())
                .dateTime(TimeUtil.getDayTime())
                .salary(salary)
                .build();
    }


}
